package ru.trilan.socialvk;
import org.json.JSONException;
import org.json.JSONArray;
import org.json.JSONObject;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
import android.util.Log;
import android.os.AsyncTask;
import android.app.AlertDialog;
import android.app.Activity;
import android.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.HttpURLConnection;
import com.vk.sdk.VKAccessToken;
import com.vk.sdk.VKSdk;
import com.vk.sdk.VKUIHelper;
import com.vk.sdk.VKCallback;
import com.vk.sdk.VKScope;
import com.vk.sdk.api.VKApi;
import com.vk.sdk.api.VKApiConst;
import com.vk.sdk.api.VKError;
import com.vk.sdk.api.VKRequest;
import com.vk.sdk.api.VKRequest.VKRequestListener;
import com.vk.sdk.api.VKParameters;
import com.vk.sdk.api.VKResponse;
import com.vk.sdk.dialogs.VKCaptchaDialog;
import com.vk.sdk.dialogs.VKShareDialog;
import com.vk.sdk.api.photo.VKUploadImage;
import com.vk.sdk.api.photo.VKImageParameters;
import com.vk.sdk.util.VKJsonHelper;
public class SocialVk extends CordovaPlugin {
private static final String TAG = "SocialVk";
private static final String ACTION_INIT = "initSocialVk";
private static final String ACTION_LOGIN = "login";
private static final String ACTION_LOGOUT = "logout";
private static final String ACTION_SHARE = "share";
private static final String ACTION_USERS_GET = "users_get";
private static final String ACTION_USERS_SEARCH = "users_search";
private static final String ACTION_USERS_IS_APP_USER = "users_isAppUser";
private static final String ACTION_USERS_GET_SUBSCRIPTIONS = "users_getSubscriptions";
private static final String ACTION_USERS_GET_FOLLOWERS = "users_getFollowers";
private static final String ACTION_WALL_POST = "wall_post";
private static final String ACTION_PHOTOS_GET_UPLOAD_SERVER = "photos_getUploadServer";
private static final String ACTION_PHOTOS_GET_WALL_UPLOAD_SERVER = "photos_getWallUploadServer";
private static final String ACTION_PHOTOS_SAVE_WALL_PHOTO = "photos_saveWallPhoto";
private static final String ACTION_PHOTOS_SAVE = "photos_save";
private static final String ACTION_FRIENDS_GET = "friends_get";
private static final String ACTION_FRIENDS_GET_ONLINE = "friends_getOnline";
private static final String ACTION_FRIENDS_GET_MUTUAL = "friends_getMutual";
private static final String ACTION_FRIENDS_GET_RECENT = "friends_getRecent";
private static final String ACTION_FRIENDS_GET_REQUESTS = "friends_getRequests";
private static final String ACTION_CALL_API_METHOD = "callApiMethod";
private CallbackContext _callbackContext;
private String savedUrl = null;
private String savedComment = null;
private String savedImageUrl = null;
final String sTokenKey = "VK_ACCESS_TOKEN";
/**
* Gets the application context from cordova's main activity.
* @return the application context
*/
private Context getApplicationContext() {
return this.getActivity().getApplicationContext();
}
private Activity getActivity() {
return (Activity)this.webView.getContext();
}
private void success() {
if(_callbackContext != null) {
_callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
_callbackContext.success();
}
}
private void fail() {
if(_callbackContext != null) {
_callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR));
_callbackContext.error("Error");
}
}
@Override
public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
this._callbackContext = callbackContext;
if(ACTION_INIT.equals(action)) {
return init(args.getString(0));
} else if (ACTION_LOGIN.equals(action)) {
JSONArray permissions = args.getJSONArray(0);
String[] perms = new String[permissions.length()];
for(int i=0; i<permissions.length(); i++) {
perms[i] = permissions.getString(i);
}
return login(perms);
} else if(ACTION_LOGOUT.equals(action)) {
VKSdk.logout();
success();
return true;
} else if (ACTION_SHARE.equals(action)) {
return shareOrLogin(args.getString(0), args.getString(1), args.getString(2));
} else if (ACTION_USERS_GET.equals(action)) {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("user_ids", args.getString(0));
params.put("fields", args.getString(1));
params.put("name_case", args.getString(2));
return usersGet(params, callbackContext);
} else if (ACTION_USERS_SEARCH.equals(action)) {
String q = args.optString(0);
JSONObject params = args.optJSONObject(0);
if(params != null)
{
return usersSearch(VKJsonHelper.toMap(params), callbackContext);
}
else if(q != null)
{
HashMap<String, Object> paramsMap = new HashMap<String, Object>();
paramsMap.put("q", q);
return usersSearch(paramsMap, callbackContext);
}
else
{
fail();
return false;
}
} else if (ACTION_USERS_IS_APP_USER.equals(action)) {
return usersIsAppUser(args.getInt(0), callbackContext);
} else if (ACTION_USERS_GET_SUBSCRIPTIONS.equals(action)) {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("user_id", args.getInt(0));
params.put("extended", args.getInt(1));
params.put("offset", args.getInt(2));
params.put("count", args.getInt(3));
params.put("fields", args.getString(4));
return usersGetSubscriptions(params, callbackContext);
} else if (ACTION_USERS_GET_FOLLOWERS.equals(action)) {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("user_id", args.getInt(0));
params.put("offset", args.getInt(1));
params.put("count", args.getInt(2));
params.put("fields", args.getString(3));
params.put("name_case", args.getString(4));
return usersGetFollowers(params, callbackContext);
} else if (ACTION_WALL_POST.equals(action)) {
String message = args.optString(0);
JSONObject params = args.optJSONObject(0);
if(params != null)
{
return wallPost(VKJsonHelper.toMap(params), callbackContext);
}
else if (message != null)
{
HashMap<String, Object> paramsMap = new HashMap<String, Object>();
paramsMap.put("message", message);
return wallPost(paramsMap, callbackContext);
}
else
{
fail();
return false;
}
} else if (ACTION_PHOTOS_GET_UPLOAD_SERVER.equals(action)) {
int album_id = args.getInt(0);
int group_id = args.getInt(1);
return photos_getUploadServer(album_id, group_id, callbackContext);
} else if (ACTION_PHOTOS_GET_WALL_UPLOAD_SERVER.equals(action)) {
int group_id = args.getInt(0);
return photos_getWallUploadServer(group_id, callbackContext);
} else if (ACTION_PHOTOS_SAVE_WALL_PHOTO.equals(action)) {
String imageBase64 = args.getString(0);
int user_id = args.getInt(1);
int group_id = args.getInt(2);
return photos_saveWallPhoto(imageBase64, user_id, group_id, callbackContext);
} else if (ACTION_PHOTOS_SAVE.equals(action)) {
String imageBase64 = args.getString(0);
int album_id = args.getInt(1);
int group_id = args.getInt(2);
return photos_save(imageBase64, album_id, group_id, callbackContext);
} else if (ACTION_FRIENDS_GET.equals(action)) {
int user_id = args.getInt(0);
String order = args.getString(1);
int count = args.getInt(2);
int offset = args.getInt(3);
String fields = args.getString(4);
String name_case = args.getString(5);
return friends_get(user_id, order, count, offset, fields, name_case, callbackContext);
} else if (ACTION_FRIENDS_GET_ONLINE.equals(action)) {
int user_id = args.getInt(0);
String order = args.getString(1);
int count = args.getInt(2);
int offset = args.getInt(3);
return friends_getOnline(user_id, order, count, offset, callbackContext);
} else if (ACTION_FRIENDS_GET_MUTUAL.equals(action)) {
int user_id = args.getInt(0);
int target_id = args.getInt(1);
String order = args.getString(2);
int count = args.getInt(3);
int offset = args.getInt(4);
return friends_getMutual(user_id, target_id, order, count, offset, callbackContext);
} else if (ACTION_FRIENDS_GET_RECENT.equals(action)) {
int count = args.getInt(0);
return friends_getRecent(count, callbackContext);
} else if (ACTION_FRIENDS_GET_REQUESTS.equals(action)) {
int offset = args.getInt(0);
int count = args.getInt(1);
int extended = args.getInt(2);
int needs_mutual = args.getInt(3);
int out = args.getInt(4);
int sort = args.getInt(5);
int suggested = args.getInt(6);
return friends_getRequests(offset, count, extended, needs_mutual, out, sort, suggested, callbackContext);
} else if (ACTION_CALL_API_METHOD.equals(action)) {
String method = args.getString(0);
JSONObject params = args.getJSONObject(1);
return callApiMethod(method, params, callbackContext);
}
Log.e(TAG, "Unknown action: "+action);
_callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "Unimplemented method: "+action));
_callbackContext.error("Unimplemented method: "+action);
return true;
}
private boolean init(String appId)
{
this.cordova.setActivityResultCallback(this);
Log.i(TAG, "VK initialize");
VKSdk.initialize(getApplicationContext());
if(_callbackContext != null) {
_callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
_callbackContext.success();
}
return true;
}
private boolean login(String[] permissions)
{
VKSdk.login(getActivity(), permissions);
return true;
}
private boolean shareOrLogin(final String url, final String comment, final String imageUrl)
{
this.cordova.setActivityResultCallback(this);
final String[] scope = new String[]{VKScope.WALL, VKScope.PHOTOS};
if(!VKSdk.isLoggedIn()) {
savedUrl = url;
savedComment = comment;
savedImageUrl = imageUrl;
VKSdk.login(getActivity(), scope);
} else {
share(url, comment, imageUrl);
}
return true;
}
private boolean share(final String url, final String comment, final String imageUrl)
{
if(url == null || comment == null) return false;
new AsyncTask<String, Void, String>() {
private Bitmap image = null;
@Override protected String doInBackground(String... args) {
if(imageUrl != null)
image = getBitmapFromURL(imageUrl);
return "";
}
@Override protected void onPostExecute(String result) {
VKShareDialog vsh = new VKShareDialog()
.setText(comment)
.setAttachmentLink("", url)
.setShareDialogListener(new VKShareDialog.VKShareDialogListener() {
public void onVkShareComplete(int postId) {
Log.i(TAG, "VK sharing complete");
}
public void onVkShareCancel() {
Log.i(TAG, "VK sharing cancelled");
}
public void onVkShareError(VKError err) {
Log.e(TAG, err.toString());
}
});
if(image != null) {
vsh.setAttachmentImages(new VKUploadImage[]{
new VKUploadImage(image, VKImageParameters.pngImage())
});
}
vsh.show(getActivity().getFragmentManager().beginTransaction(), "VK_SHARE_DIALOG");
}
}.execute();
savedUrl = null;
savedComment = null;
savedImageUrl = null;
return true;
}
@Override public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(resultCode == Activity.RESULT_CANCELED && data == null) {
// switch to another activity result callback
super.onActivityResult(requestCode, resultCode, data);
return;
}
Log.i(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
if(!VKSdk.onActivityResult(requestCode, resultCode, data, new VKCallback<VKAccessToken>() {
@Override
public void onResult(VKAccessToken res) {
// User passed Authorization
final String token = res.accessToken;
final String email = res.email;
Log.i(TAG, "VK new token: "+token);
res.saveTokenToSharedPreferences(getApplicationContext(), sTokenKey);
VKRequest request = VKApi.users().get(VKParameters.from(VKApiConst.FIELDS, "id, nickname, first_name, last_name, sex, bdate, timezone, photo, photo_big, city, country"));
request.executeWithListener(new VKRequestListener() {
@Override
public void onComplete(VKResponse response) {
try {
JSONObject loginDetails = new JSONObject();
loginDetails.put("token", token);
loginDetails.put("email", email);
loginDetails.put("user", response.json.getJSONArray("response"));
if(_callbackContext != null) {
_callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, loginDetails.toString()));
_callbackContext.success();
}
} catch (JSONException exception) {
Log.e(TAG, "JSON error:", exception);
fail();
}
}
@Override
public void onError(VKError error) {
String err = error.toString();
Log.e(TAG, err);
if(_callbackContext != null) {
_callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, err));
_callbackContext.error(error.errorMessage);
}
}
});
//share(savedUrl, savedComment, savedImageUrl);
}
@Override
public void onError(VKError error) {
// User didn't pass Authorization
String err = error.toString();
Log.e(TAG, "VK Authorization error! "+err);
//new AlertDialog.Builder(getApplicationContext()).setMessage(error.errorMessage).show();
if(_callbackContext != null) {
_callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, err));
_callbackContext.error(error.errorMessage);
}
}
})) {
super.onActivityResult(requestCode, resultCode, data);
}
}
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
if(myBitmap == null) {
Log.e(TAG, "Can't load image from "+src);
}
return myBitmap;
} catch (IOException e) {
// Log exception
Log.e(TAG, "Can't fetch image from url "+src+": "+e);
return null;
}
}
private boolean usersGet(Map<String, Object> params, CallbackContext context) {
try {
VKRequest req = VKApi.users().get(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean usersSearch(Map<String, Object> params, CallbackContext context) {
try {
VKRequest req = VKApi.users().search(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean usersIsAppUser(int user_id, CallbackContext context) {
try {
VKRequest req = VKApi.users().isAppUser(user_id);
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean usersGetSubscriptions(Map<String, Object> params, CallbackContext context) {
try {
VKRequest req = VKApi.users().getSubscriptions(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean usersGetFollowers(Map<String, Object> params, CallbackContext context) {
try {
VKRequest req = VKApi.users().getFollowers(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean wallPost(Map<String, Object> params, CallbackContext context) {
try {
VKRequest req = VKApi.wall().post(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean photos_getUploadServer(int album_id, int group_id, CallbackContext context) {
try {
VKRequest req = VKApi.photos().getUploadServer(album_id, group_id);
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean photos_getWallUploadServer(int group_id, CallbackContext context) {
try {
VKRequest req = VKApi.photos().getWallUploadServer(group_id);
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean photos_saveWallPhoto(String imageBase64, int user_id, int group_id, CallbackContext context) {
try {
VKRequest req = VKApi.uploadWallPhotoRequest(new VKUploadImage(Base64ToBitmap(imageBase64), VKImageParameters.pngImage()), user_id, group_id);
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean photos_save(String imageBase64, int album_id, int group_id, CallbackContext context) {
try {
VKRequest req = VKApi.uploadAlbumPhotoRequest(new VKUploadImage(Base64ToBitmap(imageBase64), VKImageParameters.pngImage()), album_id, group_id);
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean friends_get(int user_id, String order, int count, int offset, String fields, String name_case, CallbackContext context) {
try {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("user_id", user_id);
params.put("order", order);
params.put("count", count);
params.put("offset", offset);
params.put("fields", fields);
params.put("name_case", name_case);
VKRequest req = VKApi.friends().get(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean friends_getOnline(int user_id, String order, int count, int offset, CallbackContext context) {
try {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("user_id", user_id);
params.put("order", order);
params.put("count", count);
params.put("offset", offset);
VKRequest req = VKApi.friends().getOnline(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean friends_getMutual(int source_id, int target_id, String order, int count, int offset, CallbackContext context) {
try {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("source_id", source_id);
params.put("target_id", target_id);
params.put("order", order);
params.put("count", count);
params.put("offset", offset);
VKRequest req = VKApi.friends().getMutual(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean friends_getRecent(int count, CallbackContext context) {
try {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("count", count);
VKRequest req = VKApi.friends().getRecent(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean friends_getRequests(int offset, int count, int extended, int needs_mutual, int out, int sort, int suggested, CallbackContext context) {
try {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("offset", offset);
params.put("count", count);
params.put("extended", extended);
params.put("needs_mutual", needs_mutual);
params.put("out", out);
params.put("sort", sort);
params.put("suggested", suggested);
VKRequest req = VKApi.friends().getRequests(new VKParameters(params));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private boolean callApiMethod(String method, JSONObject params, CallbackContext context) {
try {
VKRequest req = new VKRequest(method, new VKParameters(VKJsonHelper.toMap(params)));
performRequest(req, context);
return true;
} catch(Exception ex) {
return false;
}
}
private void performRequest(VKRequest request, final CallbackContext context) {
request.executeWithListener(new VKRequestListener() {
@Override
public void onComplete(VKResponse response) {
try {
String result;
JSONObject o = response.json;
result = o.get("response").toString();
/*
if(o.optString("response")) result = o.getString("response");
else if(o.optInt("response")) result = o.getInt("response").toString();
else if(o.optJSONObject("response")) result = o.getJSONObject("response").toString();
else if(o.optJSONArray("response")) result = o.getJSONArray("response").toString();
*/
context.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
context.success();
} catch (JSONException e) {
Log.e(TAG, "JSON exception:", e);
context.sendPluginResult(new PluginResult(PluginResult.Status.ERROR));
context.error("Error");
}
}
@Override
public void onError(VKError error) {
String err = error.toString();
Log.e(TAG, err);
context.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, err));
context.error(err);
}
@Override
public void onProgress(VKRequest.VKProgressType progressType,
long bytesLoaded,
long bytesTotal)
{
//I don't really believe in progress
}
@Override
public void attemptFailed(VKRequest request, int attemptNumber, int totalAttempts) {
//More luck next time
}
});
}
Bitmap Base64ToBitmap(String myImageData)
{
byte[] imageAsBytes = Base64.decode(myImageData.getBytes(),Base64.DEFAULT);
return BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
}
}